package com.example.interceptmybatis.intercept;

import cn.hutool.core.annotation.AnnotationUtil;
import com.example.interceptmybatis.annotation.Join;
import com.example.interceptmybatis.entity.BaseEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.function.Predicate;

@Component
@Intercepts({
    @Signature(
            type = ResultSetHandler.class,
            method = "handleResultSets",
            args = {Statement.class}
    )
})
@Slf4j
public class ResultIntercept implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object result = invocation.proceed();
        getTypeAndSetValue(result);
        return result;
    }

    private void setResultValues(Field field, Object target, Predicate<Field> predicate){
        if(predicate.test(field)){
            field.setAccessible(true);
            Join join = field.getAnnotation(Join.class);
            try {
                log.info("key=======================>{}",join.key());
                String value = (String) field.get(target);
                field.set(target, value.replace(join.key(), "") );
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void getTypeAndSetValue(Object result){
        if(result instanceof BaseEntity baseEntity){
            getFieldsAndSetValue(result);
        }else if(result instanceof List<?> list){
            list.forEach(this::getFieldsAndSetValue);
        }
    }

    private void  getFieldsAndSetValue(Object target){
        if(target instanceof BaseEntity baseEntity){

            Class<? extends BaseEntity> clazz = baseEntity.getClass();
            Arrays.asList(clazz.getDeclaredFields()).forEach(field -> {
                setResultValues(field,target,v-> v.getAnnotation(Join.class)!= null);
            });
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target,this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
